#include <sys_config.h>
#include <retcode.h>
#include <types.h>
#include <api/libc/printf.h>
#include <api/libc/string.h>
#include <bus/i2c/i2c.h>
#include <osal/osal.h>
#include "tun_bf6009.h"

#if ((SYS_TUN_MODULE == BF6009) || (SYS_TUN_MODULE == ANY_TUNER))

#define BF6009_DEBUG_FLAG	1
#if(BF6009_DEBUG_FLAG)
#define NIM_BF6009_PRINTF libc_printf
#else
#define NIM_BF6009_PRINTF(...)
#endif

static struct COFDM_TUNER_CONFIG_EXT *tuner_dev_cfg[MAX_TUNER_SUPPORT_NUM];
static UINT32 tuner_cnt = 0;


unsigned int	tun_bf6009_write(UINT8 id,UINT8  uAddress, UINT8* pDataBuff,UINT8  uNbData)
{
	INT32 result;
	UINT8 data[uNbData+1];
	UINT8 u8_add;
	UINT8 u8_subadd;
	INT32 len;
	UINT8    buf[5]; 
	UINT8 i=0;

	//osal_interrupt_disable();

	u8_add = 0x30;//demod addr ;	
        buf[0]=0xFE; 	
        buf[1]=uAddress;//tuner sddr 
	 //buf[2]=uSubAddress; //register addr
	 len = uNbData; 
	
        for(i=0;i<uNbData;++i) 
       {     
       	buf[2+i]=pDataBuff[i];	
        }

	//libc_printf("%x %x %x %x\n",u8_add,uSubAddress,uNbData,* pDataBuff);
          result= i2c_gpio_write(0,u8_add,buf,len+2); 

	   if(result!=0)
	   {	
	   	NIM_BF6009_PRINTF("Tuner_wr=%d\n",result);	
	   }
	
	osal_task_sleep(10);
	//osal_interrupt_enable();

	return result;
}

unsigned int	tun_bf6009_read(UINT8 id,UINT8  uAddress, UINT8* pDataBuff,UINT8  uNbData)
{
	INT32 result;
	UINT8 data[59];		
    	UINT8 i;
	UINT8 u8_add;
	UINT8 u8_subadd;
	INT32 len;

	
	u8_add = 0x30;//uAddress;		
	data[0]=0xFE;
	data[1]=uAddress;//target address
	//data[2]=uSubAddress;//register addrs

 	result=i2c_gpio_read(0, u8_add, data, uNbData,2);
 	* pDataBuff= data[0];

	if(result!=0)
	{	
	   	NIM_BF6009_PRINTF("Tuner_rdr=%d\n",result);	
	 }
 
 	osal_task_sleep(10);
	return result;

}



/*****************************************************************************
* INT32 tun_bf6009_init(struct COFDM_TUNER_CONFIG_EXT * ptrTuner_Config)
*
* Tuner bf6009 Initialization
*
* Arguments:
*  Parameter1: struct COFDM_TUNER_CONFIG_EXT * ptrTuner_Config		: pointer for Tuner configuration structure 
*
* Return Value: INT32			: Result
*****************************************************************************/
INT32 tun_bf6009_init(UINT32 *tuner_id, struct COFDM_TUNER_CONFIG_EXT * ptrTuner_Config)
{
	if ((ptrTuner_Config == NULL) || tuner_cnt >= MAX_TUNER_SUPPORT_NUM)
		return ERR_FAILUE;

	struct COFDM_TUNER_CONFIG_EXT *cfg;	
	cfg = (struct COFDM_TUNER_CONFIG_EXT *)MALLOC(sizeof(struct COFDM_TUNER_CONFIG_EXT));
	if(cfg == NULL)
		return ERR_FAILUE;

	tuner_dev_cfg[tuner_cnt] = cfg;
	MEMCPY(cfg, ptrTuner_Config, sizeof(struct COFDM_TUNER_CONFIG_EXT));
	//tuner_id = (UINT8)tuner_cnt;
	tuner_cnt++;

	NIM_BF6009_PRINTF("BF6009_init !\n");	
	

	return SUCCESS;
}

/*****************************************************************************
* INT32 tun_bf6009_status(UINT8 *lock)
*
* Tuner read operation
*
* Arguments:
*  Parameter1: UINT8 *lock		: Phase lock status
*
* Return Value: INT32			: Result
*****************************************************************************/

INT32 tun_bf6009_status(UINT32 tuner_id, UINT8 *lock)
{
	INT32 result;
	UINT8 data;	

	struct COFDM_TUNER_CONFIG_EXT *ptrTuner_Config;

	if (tuner_id >= tuner_cnt || tuner_id >= MAX_TUNER_SUPPORT_NUM)
	{
		*lock = 0;
		return ERR_FAILUE;
	}
	ptrTuner_Config = tuner_dev_cfg[tuner_id];	
	
	result = tun_bf6009_read(ptrTuner_Config->i2c_type_id,ptrTuner_Config->cTuner_Base_Addr, &data, 1);
	*lock = ((data & 0x40) >> 6);	
	
	NIM_BF6009_PRINTF("LK=%d\n",*lock);

	return result;
}

/*****************************************************************************
* INT32 nim_bf6009_control(UINT32 freq, UINT8 bandwidth,UINT8 AGC_Time_Const,UINT8 *data,UINT8 _i2c_cmd)
*
* Tuner write operation
*
* Arguments:
*  Parameter1: UINT32 freq		: Synthesiser programmable divider
*  Parameter2: UINT8 bandwidth		: channel bandwidth
*  Parameter3: UINT8 AGC_Time_Const	: AGC time constant
*  Parameter4: UINT8 *data		: 
*
* Return Value: INT32			: Result
*****************************************************************************/
INT32 tun_bf6009_control(UINT32 tuner_id, UINT32 freq, UINT8 bandwidth,UINT8 AGC_Time_Const,UINT8 *data,UINT8 _i2c_cmd)	
{
	INT32 result;
	UINT32 tmp; 
	UINT16 Npro;	
	UINT32 freq1;
	UINT8 CP2_0, SP5, SP4, SP3_1, ATC, R2_0, AL2_0;
        UINT32 err=0;

	UINT8 i;
	struct COFDM_TUNER_CONFIG_EXT *ptrTuner_Config;

	if (tuner_id >= tuner_cnt || tuner_id >= MAX_TUNER_SUPPORT_NUM)
	{
		return ERR_FAILUE;
	}
	ptrTuner_Config = tuner_dev_cfg[tuner_id];	

//***************Prog.Byte1 and Prog.Byte2*******************
	//change ref divider according to diff bandwidth.
	/*N value*/ 
	UINT32 tuner_crystal = ptrTuner_Config->cTuner_Crystal; //khz

	if(tuner_crystal >= 1000)
	{
		// tuner crystal kHz, trans to Mhz.
		tuner_crystal = tuner_crystal/1000;
		NIM_BF6009_PRINTF("CFRSTAL  trans to Mhz=%d\n",tuner_crystal);
	}

	tmp=((freq+ptrTuner_Config->wTuner_IF_Freq+(ptrTuner_Config->cTuner_Step_Freq/2))*(ptrTuner_Config->cTuner_Ref_DivRatio))/tuner_crystal;	
	Npro=tmp/1000;
	NIM_BF6009_PRINTF("Tuner Set Freq Npro=%d\n",Npro);


//***************Cont.Byte1*******************
	if (ptrTuner_Config->cTuner_Ref_DivRatio == 28) //step 142.867k
		R2_0 = 0x01;//ISDBT
	else if (ptrTuner_Config->cTuner_Ref_DivRatio == 24) //step 166.7
		R2_0 = 0x02;
	else if (ptrTuner_Config->cTuner_Ref_DivRatio == 64)
		R2_0 = 0x00;
	else if (ptrTuner_Config->cTuner_Ref_DivRatio == 80)
		R2_0 = 0x03;
	else
	{	
		//libc_printf("R1R0 cal error! \n");
		return ERR_FAILUE;
	}


	if (AGC_Time_Const == FAST_TIMECST_AGC)
		ATC = 0x01;
	else
		ATC = 0x00;//normal mode

  AL2_0 = ptrTuner_Config->cTuner_AGC_TOP&0x07;



//***************Cont.Byte2*******************
//CP
   freq1 = freq+44000;
  if(((freq1 >=  54000) && (freq1 < 153000)) | ((freq1 >=463000) && (freq1 < 563000)))
  	CP2_0 = 0x04;
  else if ((freq1 >= 153000) && (freq1 < 161000))
  	CP2_0 = 0x01;
  else if (((freq1 >= 161000) && (freq1 < 233000)) | ((freq1 >= 426000) && (freq1 <  463000)))
  	CP2_0 = 0x03;
  else if  (((freq1 >= 233000) && (freq1 <343000))|((freq1 >= 563000) && (freq1 <613000)))
  	CP2_0 = 0x05;
   else if  ((freq1 >= 613000) && (freq1 <713000))
  	CP2_0 = 0x05;
   else if  (((freq1 >= 343000) && (freq1 <326000))|((freq1 >= 713000) && (freq1 <865000)))
  	CP2_0 = 0x05;
  else
  	{
		NIM_BF6009_PRINTF("CP error! \n");
		return ERR_FAILUE;
  	}

//Band
  if      ((freq >= 54000 ) && (freq < 161000))
  	SP3_1 = 0x01;
  else if ((freq >= 161000) && (freq < 426000))
  	SP3_1 = 0x02;
  else if ((freq >= 426000) && (freq < 865000))
  	SP3_1 = 0x04;
  else
   	{
		NIM_BF6009_PRINTF("SP3_1 error! \n");
		return ERR_FAILUE;
  	}  	
//bw=6M
  	SP4 = 0x00;
       SP5 = 0x00;



//***************Data[4:0]*******************

    data[0] = (UINT8) ((Npro>>8)&0x7F);
    data[1] = (UINT8) ((Npro)&0xFF); 
    data[2] = (UINT8) ( 0xC0 | 0x08 | R2_0 );
    data[3] = (UINT8) ((CP2_0 << 5) | (SP5 << 4) | (SP4 << 3) | SP3_1 );
    data[4] = (UINT8) ( 0x80 | (ATC << 3) | AL2_0 );

	if(ptrTuner_Config->Tuner_Write!=NULL)
	{
		if(_i2c_cmd==_1st_i2c_cmd)
		{

			NIM_BF6009_PRINTF("The Value write to bf6009 is:\n");
			for (i=0;i<5;i++)
			{
				NIM_BF6009_PRINTF("%2x \n", data[i]);
			}
			NIM_BF6009_PRINTF("\n");
			
			err+=tun_bf6009_write(ptrTuner_Config->i2c_type_id,ptrTuner_Config->cTuner_Base_Addr, data, 5);
			
		}
	}

	if ((AGC_Time_Const == FAST_TIMECST_AGC) && (_i2c_cmd==_1st_i2c_cmd))
	{
		//just wait once 100ms in ATC = 1 state.
		osal_task_sleep(100);	
	}

	return SUCCESS;	


}
#endif





